package com.mengxuegu.workflow;

import junit.framework.Assert;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Rule;
import org.junit.Test;

import java.io.File;
import java.io.InputStream;
import java.util.List;

/**
 * 动态部署
 */
//@RunWith(SpringRunner.class)
//@SpringBootTest
public class ActivitiTest5 {

    @Rule
    public ActivitiRule activitiRule = new ActivitiRule();

    @Test
    public void testDynamicDeploy() throws Exception {
        //创建bpmn模型
        BpmnModel model = new BpmnModel();
        Process process = new Process();
        model.addProcess(process);
        process.setId("my-process");

        //创建并添加bpmn元素
        process.addFlowElement(createStartEvent());
        process.addFlowElement(createUserTask("task1", "First task", "fred"));
        process.addFlowElement(createUserTask("task2", "Second task", "john"));
        process.addFlowElement(createEndEvent());

        process.addFlowElement(createSequenceFlow("start", "task1"));
        process.addFlowElement(createSequenceFlow("task1", "task2"));
        process.addFlowElement(createSequenceFlow("task2", "end"));

        // 2.生成BPMN自动布局
        new BpmnAutoLayout(model).execute();

        // 3. 部署这个BPMN模型
        Deployment deployment = activitiRule.getRepositoryService()
                .createDeployment()
                .addBpmnModel("dynamic-model.bpmn", model)
                .name("Dynamic process deployment")
                .deploy();

        System.out.println(model);

        // 4. 启动流程实例
        ProcessInstance processInstance = activitiRule.getRuntimeService()
                .startProcessInstanceByKey("my-process");

        // 5 查询任务
        List<Task> tasks = activitiRule.getTaskService()
                .createTaskQuery()
                .processInstanceId(processInstance.getId())
                .list();

        Assert.assertEquals(1, tasks.size());
        Assert.assertEquals("First task", tasks.get(0).getName());
        Assert.assertEquals("fred", tasks.get(0).getAssignee());

        // 6. 保存bpmn流程图
//        InputStream processDiagram = activitiRule.getRepositoryService()
//                .getProcessDiagram(processInstance.getProcessDefinitionId());
//        FileUtils.copyInputStreamToFile(processDiagram, new File("target/diagram.png"));

        ProcessDefinition processDefinition = activitiRule.getRepositoryService()
                .getProcessDefinition(processInstance.getProcessDefinitionId());
        if (!StringUtils.isEmpty(processDefinition.getDiagramResourceName())) {
            InputStream processDiagram = activitiRule.getRepositoryService()
                    .getResourceAsStream(deployment.getId(), processDefinition.getDiagramResourceName());
            FileUtils.copyInputStreamToFile(processDiagram, new File("target/diagram.png"));
        }

        // 7. 保存为bpmn.xml的xml类型文件
        InputStream processBpmn = activitiRule.getRepositoryService()
                .getResourceAsStream(deployment.getId(), "dynamic-model.bpmn");
        FileUtils.copyInputStreamToFile(processBpmn,
                new File("target/process.bpmn20.xml"));
    }


    //创建task
    protected UserTask createUserTask(String id, String name, String assignee) {
        UserTask userTask = new UserTask();
        userTask.setName(name);
        userTask.setId(id);
        userTask.setAssignee(assignee);
        return userTask;
    }

    //创建箭头
    protected SequenceFlow createSequenceFlow(String from, String to) {
        SequenceFlow flow = new SequenceFlow();
        flow.setSourceRef(from);
        flow.setTargetRef(to);
        return flow;
    }

    protected StartEvent createStartEvent() {
        StartEvent startEvent = new StartEvent();
        startEvent.setId("start");
        return startEvent;
    }

    protected EndEvent createEndEvent() {
        EndEvent endEvent = new EndEvent();
        endEvent.setId("end");
        return endEvent;
    }
}
